import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.font_manager import FontProperties

# 设置全局字体配置
plt.rcParams['font.size'] = 10
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['text.usetex'] = False

# 创建支持中文的字体属性
chinese_font = FontProperties(fname=mpl.font_manager.findfont('SimHei'))

# 创建图形
fig, ax = plt.subplots(figsize=(10, 6), dpi=100)

# ================== 数据准备 ==================
# 滑动窗口大小
window_sizes = np.array([1, 3, 5, 7, 10, 15])

# 隐私消耗数据（单位：ε）
privacy_consumption = {
    'GP-AdaFL (本文方案)': np.array([5.8, 4.2, 3.8, 4.1, 4.5, 5.0]),
    'DP-FedAvg (基准方案)': np.array([6.0, 6.0, 6.0, 6.0, 6.0, 6.0]),
    'DP-FedANAW (对比方案)': np.array([5.5, 4.8, 4.5, 4.7, 5.2, 5.6])
}

# ================== 绘制折线图 ==================
# 绘制GP-AdaFL折线
ax.plot(window_sizes, privacy_consumption['GP-AdaFL (本文方案)'], 
        'o-', color='#1f77b4', linewidth=2, markersize=8,
        label='GP-AdaFL (本文方案)')

# 绘制DP-FedAvg折线
ax.plot(window_sizes, privacy_consumption['DP-FedAvg (基准方案)'], 
        's--', color='#ff7f0e', linewidth=2, markersize=8,
        label='DP-FedAvg (基准方案)')

# 绘制DP-FedANAW折线
ax.plot(window_sizes, privacy_consumption['DP-FedANAW (对比方案)'], 
        'D-.', color='#2ca02c', linewidth=2, markersize=8,
        label='DP-FedANAW (对比方案)')

# 添加数据标签
for scheme, data in privacy_consumption.items():
    for i, (x, y) in enumerate(zip(window_sizes, data)):
        # 突出显示最优窗口点
        if scheme == 'GP-AdaFL (本文方案)' and x == 5:
            ax.annotate(f'{y:.1f}', xy=(x, y), xytext=(x-0.3, y-0.4),
                        fontsize=10, fontweight='bold', color='red',
                        arrowprops=dict(arrowstyle='->', color='red'))
        else:
            ax.text(x, y+0.1, f'{y:.1f}', ha='center', fontsize=9)

# ================== 设置图形属性 ==================
# 设置坐标轴
ax.set_xlabel('滑动窗口大小（轮次）', fontsize=12, fontproperties=chinese_font)
ax.set_ylabel('隐私消耗 (ε)', fontsize=12, fontproperties=chinese_font)
ax.set_title('图10：滑动窗口大小对隐私消耗的影响', fontsize=14, fontweight='bold', fontproperties=chinese_font)
ax.set_xticks(window_sizes)
ax.set_ylim(3.0, 6.5)

# 添加网格线
ax.grid(True, linestyle='--', alpha=0.3)

# 添加图例
ax.legend(prop=chinese_font, loc='upper right')

# 标注最优窗口
ax.annotate('最优窗口大小 (5轮)\n隐私消耗最低 (ε=3.8)', 
           xy=(5, 3.8), 
           xytext=(7, 4.5),
           arrowprops=dict(arrowstyle='->', color='dimgray', linewidth=1.5),
           fontsize=10, fontproperties=chinese_font,
           bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="#1f77b4", alpha=0.9))

# 添加分析结论
ax.text(0.5, -0.15, 
        '关键结论: 窗口大小=5轮时隐私消耗最低(ε=3.8)，窗口过小(1-3轮)或过大(7-15轮)均导致隐私消耗增加',
        transform=ax.transAxes, ha='center', fontsize=11, 
        fontproperties=chinese_font, 
        bbox=dict(boxstyle="round,pad=0.3", fc="#f0f0f0", ec="black", alpha=0.8))

# 添加技术标注
ax.text(0.5, -0.22, 
        "实验设置: 总隐私预算ε=5 | 数据集:MNIST | 模型:LeNet-5 | Non-IID参数α=0.5 | 客户端数量:20", 
        transform=ax.transAxes, ha='center', fontsize=10, style='italic', 
        fontproperties=chinese_font)

# 添加箭头说明
ax.annotate('窗口过小: 响应过于敏感\n导致预算频繁调整', 
           xy=(1, 5.8), 
           xytext=(1.5, 6.2),
           arrowprops=dict(arrowstyle='->', color='dimgray'),
           fontsize=9, fontproperties=chinese_font,
           bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="red", alpha=0.8))

ax.annotate('窗口过大: 响应滞后\n无法适应梯度变化', 
           xy=(15, 5.0), 
           xytext=(12, 5.5),
           arrowprops=dict(arrowstyle='->', color='dimgray'),
           fontsize=9, fontproperties=chinese_font,
           bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="red", alpha=0.8))

# 添加趋势线
ax.plot([1, 5], [5.8, 3.8], 'r--', alpha=0.3)
ax.plot([5, 15], [3.8, 5.0], 'r--', alpha=0.3)

# 调整布局
plt.tight_layout(rect=[0, 0.05, 1, 0.95])

# 保存图像
plt.savefig('window_size_privacy_impact_line.png', bbox_inches='tight', dpi=300)
plt.show()
